package com.iams.manage.service.impl;

import com.github.pagehelper.Page;
import com.iams.activiti8.domain.FormTemplates;
import com.iams.activiti8.domain.dto.ActTaskDTO;
import com.iams.activiti8.domain.dto.ActWorkflowFormDataDTO;
import com.iams.activiti8.domain.dto.HistoryDataDTO;
import com.iams.activiti8.service.IActTaskService;
import com.iams.activiti8.service.IFormTemplatesService;
import com.iams.common.core.page.PageDomain;
import com.iams.manage.domain.*;
import com.iams.manage.mapper.ArchiveMapper;
import com.iams.manage.service.*;
import com.iams.system.service.ISysUserService;
import org.activiti.api.task.model.Task;
import org.activiti.api.task.model.builders.TaskPayloadBuilder;
import org.activiti.api.task.runtime.TaskRuntime;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricVariableInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.util.*;

@Service
public class BorrowTaskServiceImpl implements IBorrowTaskService {
    
    @Autowired
    private IActTaskService actTaskService;
    @Autowired
    private TaskRuntime taskRuntime;
    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private IBorrowApprovalService borrowApprovalService;
    
    @Autowired
    private IBorrowRecordService borrowRecordService;
    
    @Autowired
    private IArchiveService archiveService;

    @Autowired
    private IFormTemplatesService formTemplatesService;

    @Autowired
    private IArchiveDestroyApprovalService archiveDestroyApprovalService;

    @Autowired
    private IArchiveFilingApprovalService archiveFilingApprovalService;

    @Autowired
    private ISysUserService sysUserService;


    @Override
    public Page<BorrowTask> selectProcessDefinitionList(PageDomain pageDomain) {
        // 获取原始的任务列表——参考原始项目不进行再更改，只在其上添加档案相关内容
        Page<ActTaskDTO> actTaskPage = actTaskService.selectProcessDefinitionList(pageDomain);

        // 创建BorrowTask的Page对象
        Page<BorrowTask> borrowTaskPage = new Page<>();
        borrowTaskPage.setTotal(actTaskPage.getTotal());
        
        // 转换任务列表
        List<BorrowTask> borrowTasks = new ArrayList<>();
        for (ActTaskDTO actTask : actTaskPage) {

            BorrowTask borrowTask = new BorrowTask();
            // 复制ActTaskDTO的基本信息
            // 此处ID为任务ID，并非实例ID
            // name也是当前的任务名
            borrowTask.setTaskId(actTask.getId());
            borrowTask.setTaskName(actTask.getName());
            // 任务状态——创建、分配等等
            borrowTask.setTaskStatus(actTask.getStatus());
            borrowTask.setTaskCreatedDate(actTask.getCreatedDate());

            // 实例名称，固定结构为：用户名 + 流程定义名
            borrowTask.setInstanceName(actTask.getInstanceName());
            // 流程key，即：process id，ArchiveDestroy等
            borrowTask.setDefinitionKey(actTask.getDefinitionKey());

            // 业务key，即：拿不到实例ID，就用业务ID进行索引咯，毕竟我们自己的数据库中保存的主要是这个，其他环节中能拿到的也只能是这个
            // 实例ID在任务也能拿，但是ActTaskDTO的定义中没添加，我们也就不改了，用业务key就好了
            borrowTask.setBusinessKey(actTask.getBusinessKey());
            
            try {
                // 根据instanceName判断是借阅任务还是销毁任务
                if (actTask.getInstanceName() != null && actTask.getInstanceName().contains("销毁申请")) {
                    // 处理销毁任务
                    ArchiveDestroyApproval destroyApproval = archiveDestroyApprovalService
                        .selectArchiveDestroyApprovalByBusinessKey(actTask.getBusinessKey());
                    
                    if (destroyApproval != null) {
                        // 设置申请人信息
                        borrowTask.setApplicantId(destroyApproval.getUserId());
                        borrowTask.setApplicantName(sysUserService.selectUserById(destroyApproval.getUserId()).getUserName());
                        borrowTask.setStartDate(destroyApproval.getStartTime());
                        borrowTask.setEndDate(destroyApproval.getEndTime());
                        borrowTask.setPurpose(destroyApproval.getPurpose());
                        
                        // 设置档案信息——此处暂未设置校验——其实应该在创建时进行校验，但是为了简单起见，暂未实现，不过这里总的来说还是不用校验
                        borrowTask.setArchiveId(destroyApproval.getArchiveId());
                        borrowTask.setArchiveName(archiveService.selectArchiveById(destroyApproval.getArchiveId()).getName());
                    } else {
                        setDefaultValues(borrowTask);
                    }
                } else if(actTask.getInstanceName() != null && actTask.getInstanceName().contains("借阅申请")){
                    // 处理借阅任务
                    Long applyId = borrowApprovalService.selectApplyIdByBusinessKey(actTask.getBusinessKey());
                    
                    if (applyId != null) {
                        // 查询借阅记录
                        BorrowRecord borrowRecord = borrowRecordService.selectBorrowRecordById(applyId);
                        if (borrowRecord != null) {
                            // 设置申请人信息
                            borrowTask.setApplicantId(borrowRecord.getUserId());
                            borrowTask.setApplicantName(borrowRecord.getUserName());
                            borrowTask.setStartDate(borrowRecord.getStartDate());
                            borrowTask.setEndDate(borrowRecord.getEndDate());
                            borrowTask.setPurpose(borrowRecord.getPurpose());
                            
                            // 查询档案信息
                            Archive archive = archiveService.selectArchiveById(borrowRecord.getArchiveId());
                            if (archive != null) {
                                borrowTask.setArchiveId(archive.getId());
                                borrowTask.setArchiveName(archive.getName());
                            } else {
                                setDefaultArchiveInfo(borrowTask);
                            }
                        } else {
                            setDefaultValues(borrowTask);
                        }
                    } else {
                        setDefaultValues(borrowTask);
                    }
                } else if(actTask.getInstanceName() != null && actTask.getInstanceName().contains("归档申请")){
                    // 归档流程
                    ArchiveFilingApproval filingApproval = archiveFilingApprovalService.selectArchiveFilingApprovalByBusinessKey(actTask.getBusinessKey());

                    if (filingApproval != null) {
                        // 设置申请人信息
                        borrowTask.setApplicantId(filingApproval.getUserId());
                        borrowTask.setApplicantName(filingApproval.getUserName());
                        borrowTask.setStartDate(filingApproval.getStartTime());
                        borrowTask.setEndDate(filingApproval.getEndTime());
                        borrowTask.setPurpose(filingApproval.getPurpose());

                        // 设置档案信息——此处暂未设置校验——其实应该在创建时进行校验，但是为了简单起见，暂未实现，不过这里总的来说还是不用校验
                        borrowTask.setArchiveId(filingApproval.getArchiveId());
                        borrowTask.setArchiveName(filingApproval.getArchiveName());
                    } else {
                        setDefaultValues(borrowTask);
                    }

                }
            } catch (Exception e) {
                setDefaultValues(borrowTask);
            }
            
            borrowTasks.add(borrowTask);
        }
        
        borrowTaskPage.addAll(borrowTasks);
        return borrowTaskPage;
    }
    
    /**
     * 设置默认的档案信息
     */
    private void setDefaultArchiveInfo(BorrowTask borrowTask) {
        borrowTask.setArchiveId(-1L);
        borrowTask.setArchiveName("测试");
    }
    
    /**
     * 设置所有默认值
     */
    private void setDefaultValues(BorrowTask borrowTask) {
        borrowTask.setApplicantId(-1L);
        borrowTask.setApplicantName("测试用户");
        setDefaultArchiveInfo(borrowTask);
        borrowTask.setStartDate(new Date());
        borrowTask.setEndDate(org.apache.commons.lang3.time.DateUtils.addDays(new Date(), 7));
        borrowTask.setPurpose("测试用途");
    }

    @Override
    public List<String> formDataShow(String taskID) {
        Task task = taskRuntime.task(taskID);
        String formKey = task.getFormKey();


        FormTemplates formTemplates = formTemplatesService.selectFormTemplatesFormKey(formKey);

        List<String> formFields = new ArrayList<>();

        formFields.add(formTemplates.getFormKey());
        formFields.add(formTemplates.getTemplatePath());
        return formFields;
    }

    @Override
    public int formDataSave(String taskID, List<ActWorkflowFormDataDTO> awfs) throws ParseException {
        Task task = taskRuntime.task(taskID);
        // 处理流程变量
        // 既然设置了表单，那么就把表单中所有的变量作为参数传入，只保留关键字段作为判断语句
        Map<String, Object> variables = new HashMap<>();
        for (ActWorkflowFormDataDTO awf : awfs) {
            if ("i".equals(awf.getControlIsParam())) {
                variables.put(awf.getControlId(), awf.getControlValue());
            }
        }
        if (task.getAssignee() == null) {
            taskRuntime.claim(TaskPayloadBuilder.claim()
                    .withTaskId(task.getId())
                    .build());
        }

        runtimeService.setVariables(task.getProcessInstanceId(), variables);

        taskRuntime.complete(TaskPayloadBuilder.complete()
                .withTaskId(taskID)
                .withVariables(variables)
                .build());
        return 1;
    }

    @Override
    public List<Map<String, Object>> historyFormDataShow(String taskID){

        String processInstanceId = taskRuntime.task(taskID).getProcessInstanceId();
        HistoryDataDTO historyDataDTO = new HistoryDataDTO();

        List<HistoricTaskInstance> historicTasks = historyService.createHistoricTaskInstanceQuery()
                .processInstanceId(processInstanceId)
                .orderByTaskCreateTime()
                .asc()
                .list();

        // 2. 获取每个任务的审批信息
        List<Map<String, Object>> taskHistoryList = new ArrayList<>();

        for (HistoricTaskInstance historicTask : historicTasks) {

            Map<String, Object> taskHistory = new HashMap<>();
            // 基本任务信息
            taskHistory.put("taskId", historicTask.getId());
            taskHistory.put("taskName", historicTask.getName());
            taskHistory.put("assignee", historicTask.getAssignee());
            taskHistory.put("startTime", historicTask.getStartTime());
            taskHistory.put("endTime", historicTask.getEndTime());

            // 获取该任务的变量
            List<HistoricVariableInstance> taskVariables = historyService.createHistoricVariableInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .taskId(historicTask.getId())
                    .list();

            Map<String, Object> variables = new HashMap<>();
            for (HistoricVariableInstance variable : taskVariables) {
                variables.put(variable.getVariableName(), variable.getValue());
            }

            // 添加审批结果和意见
            if (variables.containsKey("approvalResult")) {
                taskHistory.put("approvalResult", variables.get("approvalResult"));
            }
            if (variables.containsKey("approvalComment")) {
                taskHistory.put("approvalComment", variables.get("approvalComment"));
            }

            taskHistoryList.add(taskHistory);
        }



        return taskHistoryList;
    }

}
